package com.cold.legendary.mock.spring.support.listener;

import com.cold.legendary.mock.annotation.LMockInjectBean;
import com.cold.legendary.mock.aware.MockInjectAware;
import com.cold.legendary.mock.context.prepare.PrepareContextManager;
import com.cold.legendary.mock.context.runnable.RunContextManager;
import com.cold.legendary.mock.context.whole.WholeMockContext;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Modifier;

import static org.springframework.core.annotation.AnnotationUtils.getAnnotation;

/**
 * 单元测试自定义监听器
 *
 * @author cold
 * @since  2022/1/18
 */
public class LMockContextListener extends AbstractTestExecutionListener {

    private MockInjectAware mockInjectAware = MockInjectAware.getInstance();

    /**
     * 单元测试类加载前执行自定义逻辑
     */
    @Override
    public void beforeTestClass(TestContext testContext) throws Exception {
        ApplicationContext testApplicationContext = testContext.getApplicationContext();
        Class testClazz = testContext.getTestClass();

        //加载单元测试中所有指定注解类,解析完以后放置到mock上下文中
        ReflectionUtils.doWithFields(testClazz, field -> {
            LMockInjectBean lMockInjectBeanAnn = getAnnotation(field, LMockInjectBean.class);
            if (lMockInjectBeanAnn != null) {
                if (Modifier.isStatic(field.getModifiers())) {
                    return;
                }
                Object mockInjectBeanObject = testApplicationContext.getBean(field.getName());
                mockInjectAware.loadInjectMockBeans(mockInjectBeanObject.getClass(), mockInjectBeanObject, lMockInjectBeanAnn);
            }
        });
    }

    @Override
    public void afterTestClass(TestContext testContext) throws Exception {
        WholeMockContext.getInstance().cleanWholeMockContext();
        PrepareContextManager.cleanPreMockContext();
        RunContextManager.cleanRunMockContext();
    }
}
